home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / sossnt.zip / SOSSNT / SRC / NFS.C < prev    next >
C/C++ Source or Header  |  1993-03-04  |  31KB  |  1,078 lines

  1. /*
  2.  *  nfs.c --
  3.  *      NFS server implementation for PC.  Runs on top of the
  4.  *      net daemon (netd.c).
  5.  *
  6.  *  Author:
  7.  *      See-Mong Tan, 6/12/88.
  8.  *  Modified by:
  9.  *    Rich Braun @ Kronos, 2/15/91
  10.  *
  11.  *  Revision history:
  12.  *  
  13.  * $Log: nfs.c_v $
  14.  * Revision 1.6  1991/05/13  17:45:56  richb
  15.  * Correct the NFS_STATFS call so it doesn't return an error if there
  16.  * are 0 free blocks in a filesystem.
  17.  * Add support for '-b' command line option so the administrator can
  18.  * specify read/write block sizes.
  19.  *
  20.  * Revision 1.5  1991/04/11  20:41:26  richb
  21.  * Validate pathnames before invoking pntoin, to prevent crashes.
  22.  *
  23.  * Revision 1.4  1991/03/15  22:41:19  richb
  24.  * Numerous patches.
  25.  *
  26.  * Revision 1.3  1991/02/20  19:15:39  richb
  27.  * Minor changes for file_create; add RCS headers.
  28.  *
  29.  */
  30.  
  31. #ifdef RCSID
  32. static char _rcsid_ = "$Id: nfs.c_v 1.6 1991/05/13 17:45:56 richb Exp $";
  33. #endif
  34.  
  35. #include "common.h"
  36. #include "files.h"
  37. #include <direct.h>        /* directory ops */
  38. #include "..\rpc\a_unix.h"
  39.  
  40. static char *reply_err = "RPC error:  cannot transmit\n";
  41. static char *mem_err   = "malloc:  no more memory\n";
  42.  
  43. /*
  44.  *  bool_t nfs_init() --
  45.  *      Initializes NFS server.  Creates and registers transport
  46.  *      handle for NFS server.  Returns TRUE if successful, or FALSE
  47.  *      if an error occurred.
  48.  */
  49. bool_t nfs_init()
  50. {
  51.     SVCXPRT *transp;
  52.  
  53.     /* struct sockaddr_in addr; */
  54.  
  55.     static void nfs_dispatch(struct svc_req *, SVCXPRT *);
  56.  
  57.     SOCKET nfs_sock;
  58.     SOCKADDR_IN local_sin; /* Local socket */
  59.  
  60.     nfs_sock = socket( PF_INET, SOCK_DGRAM, 0);
  61.     if (nfs_sock == INVALID_SOCKET) {
  62.         (void) fprintf(stderr, "cannot create nfs socket\n");
  63.         return FALSE;
  64.     }
  65.  
  66.     local_sin.sin_family = AF_INET;
  67.     local_sin.sin_port = htons(NFS_PORT);
  68.     local_sin.sin_addr.s_addr = INADDR_ANY;
  69.  
  70.       if (bind( nfs_sock, (SOCKADDR*)(&local_sin), sizeof(local_sin)) == SOCKET_ERROR) {
  71.         fprintf(stderr,"bind() failed");
  72.         return FALSE;
  73.     }
  74.  
  75.     if ((transp = svcudp_create(nfs_sock, 1,local_sin.sin_port)) == (SVCXPRT *) NULL) {
  76.         (void) fprintf(stderr, "cannot create udp handle\n");
  77.         closesocket(nfs_sock);
  78.         return FALSE;
  79.     }
  80.     if (! svc_register(transp, NFS_PROGRAM, NFS_VERSION, nfs_dispatch, 
  81.                IPPROTO_UDP)) {
  82.         (void) fprintf(stderr, "cannot register handle\n");
  83.         closesocket(nfs_sock);
  84.         return FALSE;
  85.     }
  86.  
  87.     return TRUE;
  88. }
  89.  
  90. /*
  91.  *  void nfs_dispatch(struct svc_req *req, SVCXPRT *transp) --
  92.  *      NFS server dispatch routine.
  93.  */
  94. static void nfs_dispatch(req, transp)
  95.      struct svc_req *req;
  96.      SVCXPRT *transp;
  97. {
  98. #if DEBUG
  99. static char *names[] = {"NULL", "GETATTR", "SETATTR", "ROOT", "LOOKUP",
  100.             "READLINK", "READ", "WRITECACHE", "WRITE", "CREATE",
  101.             "REMOVE", "RENAME", "LINK", "SYMLINK", "MKDIR",
  102.             "RMDIR", "READDIR", "STATFS", "<invalid>"};
  103.     DBGPRT1 (nfsdisp, ">>> NFS_%s", names[(req->rq_proc > NFS_STATFS) ?
  104.                   NFS_STATFS+1 : req->rq_proc]);
  105. #endif
  106.  
  107.     /* find which procedure to call */
  108.     switch((int) req->rq_proc) {    
  109.  
  110.       case NFS_GETATTR: nfs_getattr(transp, req);    break;
  111.       case NFS_NULL:    nfs_null(transp, req);        break;
  112.       case NFS_READ:    nfs_read(transp, req);        break;
  113.       case NFS_WRITE:    nfs_write(transp, req);        break;
  114.       case NFS_STATFS:    nfs_statfs(transp, req);    break;
  115.       case NFS_LOOKUP:    nfs_lookup(transp, req);    break;
  116.       case NFS_READDIR:    nfs_readdir(transp, req);    break;
  117.       case NFS_CREATE:    nfs_create(transp, req);    break;
  118.       case NFS_MKDIR:    nfs_mkdir(transp, req);        break;
  119.       case NFS_REMOVE:    nfs_remove(transp, req);    break;
  120.       case NFS_RMDIR:    nfs_rmdir(transp, req);        break;
  121.       case NFS_RENAME:    nfs_rename(transp, req);    break;
  122.       case NFS_SETATTR:    nfs_setattr(transp, req);    break;
  123.       case NFS_LINK:    nfs_link(transp, req);        break;
  124.       case NFS_SYMLINK:    nfs_symlink(transp, req);    break;
  125.       default:
  126.     DBGPRT1 (nfsdisp, "unsupp procedure %d",
  127.          req->rq_proc);
  128.     nfs_error(transp, req);
  129.     break;
  130.     }
  131. }
  132.  
  133. /*
  134.  *  void nfs_null(SVCXPRT *xprt, struct svc_req *req) --
  135.  *      Sends an empty reply.  Used for "ping-ing" the nfs server.
  136.  */
  137. void nfs_null(xprt, req)
  138.     SVCXPRT *xprt;
  139.     struct svc_req *req;
  140. {
  141.     if (! svc_sendreply(xprt, xdr_void, (char *) NULL))
  142.         (void) fprintf(stderr, reply_err);
  143. }
  144.  
  145. /*
  146.  *  void nfs_read(SVCXPRT *xprt, struct svc_req *req) --
  147.  *      Reads requested file and sends it over the wire.
  148.  */
  149. void nfs_read(xprt, req)
  150.     SVCXPRT *xprt;
  151.     struct svc_req *req;
  152. {
  153.     struct nfsreadargs *r_args;        /* the argument */
  154.     struct nfsrdresult r_rslt;        /* the read result */
  155.     char   databuf [NFS_MAXDATA];
  156.     u_long count;            /* request size */
  157.     int    bytes;            /* bytes read */
  158.  
  159.     r_args = (struct nfsreadargs *) malloc(sizeof(struct nfsreadargs));
  160.     if (r_args == NULL) {
  161.     (void) fprintf(stderr, mem_err);
  162.     abort();
  163.     }
  164.     (void) bzero((char*)r_args, sizeof(struct nfsreadargs));
  165.     if (! svc_getargs(xprt, xdr_readargs, r_args)) {
  166.     svcerr_decode(xprt);
  167.     (void) free(r_args);
  168.     return;
  169.     }
  170.     (void) bzero((char*)&r_rslt, sizeof(struct nfsrdresult));
  171.  
  172.     /* set pointer to data in results struct */
  173.     r_rslt.rr_data = databuf;
  174.     count = r_args->ra_count;
  175.  
  176.     /* evaluate buffer count argument */
  177.     if (count > (unsigned) nfsrd_size) {
  178.     count = nfsrd_size;
  179.     fprintf (stderr, "NFS_READ: truncating req. from %ld\n",
  180.          r_args->ra_count);
  181.     }
  182.  
  183.     /* get attributes */
  184.     if (inattrget (r_args->ra_fhandle.f.fh_fno, &r_rslt.rr_attr) ==
  185.     (struct nfsfattr *) NULL)
  186.       r_rslt.rr_status = NFSERR_STALE;
  187.     else  {
  188.     if ((bytes = file_read(r_args->ra_fhandle.f.fh_fno,
  189.                    r_args->ra_offset, count,
  190.                    r_rslt.rr_data)) == -1) {
  191.         DBGPRT1 (nfserr, "file_read error %d", errno);
  192.         r_rslt.rr_status = puterrno (errno);
  193.     }
  194.     else {
  195. #ifdef DEBUG
  196.         char name [MAXPATHNAMELEN];
  197. #endif
  198.         DBGPRT4 (nfsread, "%s: %ld/%d bytes at %ld",
  199.              intopn (r_args->ra_fhandle.f.fh_fno, name),
  200.              r_args->ra_count, bytes, r_args->ra_offset);
  201.         r_rslt.rr_bufsize = nfsrd_size;
  202.         r_rslt.rr_count = bytes;
  203.         r_rslt.rr_status = NFS_OK;
  204.         r_rslt.rr_bp = NULL;
  205.         r_rslt.rr_vp = NULL;
  206.     }
  207.     }
  208.     if (! svc_sendreply(xprt, xdr_rdresult, &r_rslt))
  209.       (void) fprintf(stderr, reply_err);
  210.     else if (NFS_VERBOSE)
  211.       (void) printf(">>> NFS_READ\n");
  212.  
  213.     /* free arguments */    
  214.     svc_freeargs(xprt, xdr_readargs, r_args);
  215. }
  216.  
  217. /*
  218.  *  void nfs_error(SVCXPRT *xprt, struct svc_req *req) --
  219.  *      Returns nfs error message.
  220.  */
  221. void nfs_error(xprt, req)
  222.     SVCXPRT *xprt;
  223.     struct svc_req *req;
  224. {
  225.     (void) fprintf(stderr, 
  226.         ">>> NFS_ERROR: procedure %d not supported\n", req->rq_proc);
  227.     svcerr_noproc(xprt);        /* send server error reply msg */
  228. }
  229.  
  230. /*
  231.  *  void nfs_getattr(SVCXPRT *xprt, struct svc_req *req) --
  232.  *      Gets file attributes.
  233.  */
  234. void nfs_getattr(xprt, req)
  235.     SVCXPRT *xprt;
  236.     struct svc_req *req;
  237. {
  238.     fhandle_t *fhp;            /* file handle is argument */
  239.     struct nfsattrstat attr;    /* return attributes */    
  240.     char *fullpath, path[MAXPATHNAMELEN];    /* full DOS path name */
  241.  
  242.     fhp = (fhandle_t *) malloc(sizeof(fhandle_t));
  243.     if (fhp == NULL) {
  244.     (void) fprintf(stderr, mem_err);
  245.     abort();
  246.     }
  247.     (void) bzero((char*)fhp, sizeof(fhandle_t));
  248.     if (! svc_getargs(xprt, xdr_fhandle, fhp)) {
  249.     (void) fprintf(stderr, "nfs_getattr: cannot read args\n");
  250.     svcerr_decode(xprt);
  251.     (void) free(fhp);
  252.     return;
  253.     }
  254.  
  255.     /* Check the validity of the file handle */
  256.     if (!checkfh (fhp))
  257.       attr.ns_status = NFSERR_STALE;
  258.     else {
  259.     /* clear out return attributes */
  260.     (void) bzero((char*)&attr, sizeof(struct nfsattrstat));
  261.     fullpath = intopn(fhp->f.fh_fno, path);    /* path from inode */
  262.  
  263.     if (! file_getattr(fullpath, &(attr.ns_attr)))
  264.       attr.ns_status = NFSERR_NOENT;
  265.     else
  266.       attr.ns_status = NFS_OK;
  267.     }
  268. #if 1
  269.     {
  270.       /* Hack:  tell the caller he is the owner */
  271.       struct authunix_parms *unix_cred;
  272.       unix_cred = (struct authunix_parms *) req->rq_clntcred;
  273.       attr.ns_attr.na_uid =  (u_long) unix_cred->aup_uid;
  274.     }
  275. #endif
  276.  
  277.     if (! svc_sendreply(xprt, xdr_attrstat, &attr))
  278.       (void) fprintf(stderr, reply_err);
  279.     else if (NFS_VERBOSE)
  280.       (void) printf(">>> NFS_GETATTR: %s\n", fullpath);
  281.  
  282.     svc_freeargs(xprt, xdr_fhandle, fhp);
  283. }
  284.  
  285. /*
  286.  *  void nfs_statfs(SVCXPRT *xprt, struct svc_req *req) --
  287.  *      Returns file system status
  288.  */
  289. void nfs_statfs(xprt, req)
  290.     SVCXPRT *xprt;
  291.     struct svc_req *req;
  292. {
  293.     struct nfsstatfs fs;
  294.     fhandle_t *fhp;
  295.  
  296.     fhp = (fhandle_t *) malloc(sizeof(fhandle_t));
  297.     if (fhp == NULL) {
  298.     (void) fprintf(stderr, mem_err);
  299.     abort();
  300.     }
  301.     (void) bzero((char*)fhp, sizeof(fhandle_t));
  302.     if (! svc_getargs(xprt, xdr_fhandle, fhp)) {
  303.     svcerr_decode(xprt);
  304.     (void) free(fhp);
  305.     return;
  306.     }
  307.  
  308.     /* Check the validity of the file handle */
  309.     if (!checkfh (fhp))
  310.       fs.fs_status = NFSERR_STALE;
  311.     else {
  312.     /* clear out results struct */
  313.     (void) bzero((char*)&fs, sizeof(struct nfsstatfs));
  314.     /* set up struct */
  315.     if (file_freeblocks(fhp->f.fh_fsid, &(fs.fs_bfree), 
  316.                   &(fs.fs_blocks)) != 0) {
  317.         DBGPRT1 (nfserr, "statfs error %d", errno);
  318.         fs.fs_status = NFSERR_IO;
  319.     }
  320.     else {
  321.         fs.fs_tsize = NFS_MAXDATA;
  322.         fs.fs_bsize = FS_BLOCKSIZE;
  323.         fs.fs_status = NFS_OK;
  324.         fs.fs_bavail = fs.fs_bfree;
  325.     }
  326.     }
  327.     if (! svc_sendreply(xprt, xdr_statfs, &fs))
  328.       (void) fprintf(stderr, reply_err);
  329.     else if (NFS_VERBOSE)
  330.       (void) printf(">>> NFS_STATFS: drive %d\n", fhp->f.fh_fsid);
  331.     svc_freeargs(xprt, xdr_fhandle, fhp);
  332. }
  333.  
  334. /*
  335.  *  void nfs_readdir(SVCXPRT *xprt, struct svc_req *req) --
  336.  *      Read a directory.
  337.  */
  338. void nfs_readdir(xprt, req)
  339.     SVCXPRT *xprt;
  340.     struct svc_req *req;
  341. {
  342.     struct nfsrddirargs *args;        /* args */
  343.     struct nfsrddirres res;            /* results */
  344.     u_long nodeid;                /* inode number */
  345.     static u_long offs;                /* offset */
  346.     static int bytes;                /* # of dir bytes read */
  347.     int maxbytes;
  348.     struct udirect *udp;            /* directory cookie array */
  349. #define SUD    32                /* increment for offsets */
  350.     static u_long prevfh_no;            /* previous path handle */
  351.     static char prevudp[NFS_MAXDATA + sizeof (struct udirect)];
  352.     static u_long prevoffs;            /* previous offset */
  353.     static int  preveof;            /* previous EOF flag */
  354.  
  355.     args = (struct nfsrddirargs *) malloc(sizeof(struct nfsrddirargs));
  356.     if (args == NULL) {
  357.     (void) fprintf(stderr, mem_err);
  358.     abort();
  359.     }
  360.     (void) bzero((char*)args, sizeof(struct nfsrddirargs));
  361.     if (! svc_getargs(xprt, xdr_rddirargs, args)) {
  362.     svcerr_decode(xprt);
  363.     (void) free(args);
  364.     return;
  365.     }
  366.     maxbytes = (args->rda_count > (unsigned)nfsrd_size ? nfsrd_size : args->rda_count);
  367.     if (maxbytes == 0)
  368.       maxbytes = nfsrd_size;
  369.  
  370.     nodeid   = args->rda_fh.f.fh_fno;
  371.  
  372.     /* Check the validity of the file handle */
  373.     if (!checkfh (&args->rda_fh))
  374.       res.rd_status = NFSERR_STALE;
  375.  
  376.     else {
  377.     /* clear out results */
  378.     (void) bzero((char*)&res, sizeof(struct nfsrddirres));    /* zero results */
  379.     res.rd_bufsize = args->rda_count;             /* size of clnt req */
  380.     res.rd_status  = NFS_OK;
  381.  
  382.     /* point to directory entries block */
  383.     res.rd_entries = (struct udirect *) prevudp;
  384.     udp = res.rd_entries;
  385.  
  386.     /* see if this is an identical request */
  387.     if (args->rda_offset != 0L && args->rda_offset == prevoffs &&
  388.           prevfh_no == nodeid) {
  389.         res.rd_offset = offs;
  390.         res.rd_size   = bytes;
  391.         res.rd_eof    = preveof;
  392.         DBGPRT1 (nfsread, "READDIR (same %ld)", args->rda_offset);
  393.     }
  394.     else {
  395.         /* clear out the udp */
  396.         (void) bzero((char*)prevudp, sizeof prevudp);
  397.  
  398.         /* read until filled */
  399.         res.rd_eof    = FALSE;
  400.         offs          = args->rda_offset;
  401.         prevoffs      = offs;
  402.         bytes          = 0;
  403.         prevfh_no     = nodeid;
  404.  
  405.         while (bytes < maxbytes) {
  406.         int rstat;        /* read status */
  407.  
  408.         rstat = file_rddir(nodeid, offs, udp);
  409.         if (rstat == -1) {            /* error reading */
  410.             res.rd_status = NFSERR_NOENT;
  411.             break;
  412.         }
  413.  
  414.         /* space for more? */
  415.         if ((bytes + udp->d_reclen) <= maxbytes) {
  416.             bytes += udp->d_reclen;
  417.  
  418.             /* Break out of loop if this is the last entry. */
  419.             if (rstat == 0) {
  420.             res.rd_eof = TRUE;
  421.             break;
  422.             }
  423.  
  424.             /* Point to next entry */
  425.             udp = (struct udirect *) ((char *) udp + UDIRSIZ(udp));
  426.             offs += SUD;            /* next offset */
  427.         }
  428.         else
  429.           break;
  430.         }
  431.         /* broke out of the loop */
  432.         if (res.rd_status == NFS_OK) {        /* good read */
  433.         res.rd_offset = offs;        /* next offset */
  434.         res.rd_size = bytes;        /* # of bytes */
  435.         res.rd_bufsize = bytes + 128;   /* Add enough extra for */
  436.                         /* XDR routine */
  437.         }
  438.         preveof = res.rd_eof;
  439.         DBGPRT4 (nfsread, "READDIR offset = %ld..%ld, bytes = %d  %s",
  440.              prevoffs / SUD, offs / SUD,
  441.              bytes, res.rd_eof ? "***EOF***" : "");
  442.     }
  443.     }
  444.  
  445.     if (! svc_sendreply(xprt, xdr_putrddirres, &res))
  446.       (void) fprintf(stderr, reply_err);
  447.     else if (NFS_VERBOSE)
  448.       (void) printf(">>> NFS_READDIR\n");
  449.  
  450.     /* free space */
  451.     svc_freeargs(xprt, xdr_rddirargs, args);
  452. #undef SUD
  453. }
  454.  
  455. /*
  456.  *  void nfs_lookup(SVCXPRT *xprt, struct svc_req *req) --
  457.  *      Directory lookup.
  458.  */
  459. void nfs_lookup(xprt, req)
  460.     SVCXPRT *xprt;
  461.     struct svc_req *req;
  462. {
  463.     struct nfsdiropargs *args;    /* arguments to call */
  464.     struct nfsdiropres res;        /* and results */
  465.     struct nfsfattr attr;        /* return attributes */
  466.     char *fullpath, path[MAXPATHNAMELEN]; /* path of file looked up */
  467.     
  468.     args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
  469.     if (args == NULL) {
  470.         (void) fprintf(stderr, mem_err);
  471.         abort();
  472.     }
  473.     (void) bzero((char*)args, sizeof(struct nfsdiropargs));
  474.     if (! svc_getargs(xprt, xdr_diropargs, args)) {
  475.         svcerr_decode(xprt);
  476.         (void) free(args);
  477.         return;
  478.     }
  479.  
  480.     /* Check the validity of the parent's handle */
  481.     if (!checkfh (&args->da_fhandle))
  482.       res.dr_status = NFSERR_STALE;
  483.     else {
  484.         /* clear out return struct */
  485.         (void) bzero((char*)&res, sizeof(struct nfsdiropres));
  486.  
  487.         DBGPRT2 (nfslookup, "ino=%d  path=%s", args->da_fhandle.f.fh_fno,path);
  488.  
  489.         fullpath = intopn(args->da_fhandle.f.fh_fno, path);/* path from */
  490.                                 /* inode of parent */
  491.         if (fullpath != NULL) {
  492.         /* 
  493.          * extra code here to handle XCOPY's brain-damaged
  494.          * way of passing wildcards when it really shouldn't.
  495.          */
  496.         int i;
  497.         int namelen;
  498.  
  499.         namelen = strlen(args->da_name);
  500.         for(i = 0; i < namelen; i++) {     /* scan the name */
  501.             if ((args->da_name)[i] == '*' || 
  502.                 (args->da_name)[i] == '?') {
  503.                 res.dr_status = NFSERR_NOENT;
  504.                 goto end;
  505.             }
  506.         }
  507.         /* end of extra code */
  508.         
  509.         if (strcmp(args->da_name, "..") == 0) {    /* asking for parent */
  510.             fullpath = intopn(parentinode(
  511.                     args->da_fhandle.f.fh_fno), path);
  512.         }
  513.         else if (strcmp(args->da_name , ".") != 0) {
  514.             (void) strcat(fullpath, "\\");    /* append seperator */
  515.             (void) strcat(fullpath, args->da_name);    
  516.             (void) strtolower(fullpath);    /* all lower case */
  517.         }
  518.         }
  519.         res.dr_status = validate_path (fullpath);
  520.  
  521.         DBGPRT1 (nfslookup, "fullpath = %s", fullpath);
  522.  
  523.         if (res.dr_status == NFS_OK) {
  524.         if ( ! file_getattr(fullpath, &attr)) {
  525.             DBGPRT0 (nfslookup, "no such file");
  526.             res.dr_status = NFSERR_NOENT;
  527.         }
  528.         else {        /* copy the attributes over */
  529.             res.dr_attr = attr;
  530.             res.dr_status = NFS_OK;        /* set proper status */
  531.             /* get a fhandle for it */
  532.             if (strcmp(args->da_name, ".") != 0)
  533.               res.dr_fhandle = pntofh(fullpath);
  534.             else
  535.               res.dr_fhandle = args->da_fhandle;
  536. #if 1
  537.             {
  538.             /* Hack:  tell the caller he is the owner */
  539.             struct authunix_parms *unix_cred;
  540.             unix_cred = (struct authunix_parms *) req->rq_clntcred;
  541.             res.dr_attr.na_uid =  (u_long) unix_cred->aup_uid;
  542.             }
  543. #endif
  544.         }
  545.         }
  546.     }
  547.     /* reply to caller */
  548. end:    if (NFS_VERBOSE)
  549.         (void) printf(">>> NFS_LOOKUP: %s\n", fullpath);
  550.     if (! svc_sendreply(xprt, xdr_diropres, &res))
  551.         (void) fprintf(stderr, reply_err);
  552.  
  553.     /* free used space */
  554.     svc_freeargs(xprt, xdr_diropargs, args);
  555. }
  556.  
  557. /*
  558.  *   void nfs_write(SVCXPRT *xprt, struct svc_req *req) --
  559.  *      Do an atomic write operation.
  560.  */
  561. void nfs_write(xprt, req)
  562.     SVCXPRT *xprt;
  563.     struct svc_req *req;
  564. {
  565.     struct nfswriteargs *args;        /* args */
  566.     struct nfsattrstat res;            /* return stat */
  567.  
  568.     /* alloc space for args */
  569.     args = (struct nfswriteargs *) malloc(sizeof(struct nfswriteargs));
  570.     if (args == NULL) {
  571.         (void) fprintf(stderr, mem_err);
  572.         abort();
  573.     }
  574.     (void) bzero((char*)args, sizeof(struct nfswriteargs));
  575.     if (! svc_getargs(xprt, xdr_writeargs, args)) {
  576.         svcerr_decode(xprt);
  577.         (void) free(args);
  578.         return;
  579.     }
  580.     if (NFS_READONLYFS) {
  581.         nfserr_readonlyfs(xprt, xdr_writeargs, args);
  582.         return;
  583.     }
  584.     (void) bzero((char*)&res, sizeof(struct nfsattrstat));
  585.     /* evaluate buffer count argument */
  586.     if (args->wa_count > (unsigned) nfswr_size) {
  587.         res.ns_status = NFSERR_IO;
  588.         goto reply;
  589.     }
  590.     res.ns_status = file_write(args->wa_fhandle.f.fh_fno, args->wa_offset,
  591.                    args->wa_count, args->wa_data);
  592.     if (res.ns_status == NFS_OK) {
  593.         /* get file attributes */
  594.         if (inattrget (args->wa_fhandle.f.fh_fno, &res.ns_attr) ==
  595.             (struct nfsfattr *) NULL) {
  596.             res.ns_status = NFSERR_STALE;
  597.         }
  598.     }
  599.     else
  600.         DBGPRT2 (nfserr, "write %ld, error %d",
  601.              args->wa_fhandle.f.fh_fno, res.ns_status);
  602.  
  603.       reply:
  604.     if (! svc_sendreply(xprt, xdr_attrstat, &res))
  605.         (void) fprintf(stderr, reply_err);
  606.     else if (NFS_VERBOSE)
  607.         (void) printf(">>> NFS_WRITE: %ld\n",
  608.                   args->wa_fhandle.f.fh_fno);
  609.  
  610.     svc_freeargs(xprt, xdr_writeargs, args);    /* free all data */
  611. }
  612.  
  613. /*
  614.  *  void nfs_create(SVCXPRT *xprt, struct svc_req *req) --
  615.  *      Create a file.
  616.  */
  617. void nfs_create(xprt, req)
  618.     SVCXPRT *xprt;
  619.     struct svc_req *req;
  620. {
  621.     struct nfscreatargs *args;            /* create args */
  622.     struct nfsdiropres res;            /* return result */
  623.     char *fullpath, path[MAXPATHNAMELEN];    /* full name */
  624.     struct authunix_parms *unix_cred;
  625.  
  626.     args = (struct nfscreatargs *) malloc(sizeof(struct nfscreatargs));
  627.     if (args == NULL) {
  628.         (void) fprintf(stderr, mem_err);
  629.         abort();
  630.     }
  631.     (void) bzero((char*)args, sizeof(struct nfscreatargs));
  632.     if (! svc_getargs(xprt, xdr_creatargs, args)) {
  633.     svcerr_decode(xprt);
  634.     (void) free(args);
  635.     return;
  636.     }
  637.     if (NFS_READONLYFS) {        /* read only file system */
  638.     nfserr_readonlyfs(xprt, xdr_creatargs, args);
  639.     return;
  640.     }
  641.  
  642.     /* Check the validity of the file handle */
  643.     if (!checkfh (&args->ca_da.da_fhandle))
  644.       res.dr_status = NFSERR_STALE;
  645.     else {
  646.     /* clear out return struct */
  647.     (void) bzero((char*)&res, sizeof(struct nfsdiropres));
  648.     fullpath = intopn(args->ca_da.da_fhandle.f.fh_fno, path);
  649.     if (fullpath != NULL) {
  650.         (void) strcat(fullpath, "\\");        /* make rest of name */
  651.         (void) strcat(fullpath, args->ca_da.da_name);
  652.         (void) strtolower (fullpath);        /* force lower case */
  653.     }
  654.     if (file_getattr(fullpath, &(res.dr_attr))) {    /* file exists */
  655.         res.dr_status = NFSERR_EXIST;
  656.     }
  657.     /* fill in default UID/GID info */
  658.     unix_cred = (struct authunix_parms *) req->rq_clntcred;
  659.     if (args->ca_sa.sa_uid == -1)
  660.       args->ca_sa.sa_uid = (u_long) unix_cred->aup_uid;
  661.     if (args->ca_sa.sa_gid == -1)
  662.       args->ca_sa.sa_gid = (u_long) unix_cred->aup_gid;
  663.  
  664.     /* create a file */
  665.     res.dr_status = file_create(fullpath, &(args->ca_sa), &res.dr_attr);
  666.     if (res.dr_status == NFS_OK) {            /* no errors */
  667.         /* make file handle */
  668.         res.dr_fhandle = pntofh(fullpath);
  669.     }
  670.     }
  671.     if (! svc_sendreply(xprt, xdr_diropres, &res))
  672.       (void) fprintf(stderr, reply_err);
  673.     else if (NFS_VERBOSE)
  674.       (void) printf(">>> NFS_CREATE: %s\n", fullpath);
  675.  
  676.     /* free all data */
  677.     svc_freeargs(xprt, xdr_creatargs, args);
  678. }
  679.     
  680. /*
  681.  *  void nfs_mkdir(SVCXPRT *xprt, struct svc_req *req) --
  682.  *      Make a directory request.  All DOS directories are readable and
  683.  *    writeable, hence the set attribute field is ignored.
  684.  */
  685. void nfs_mkdir(xprt, req)
  686.     SVCXPRT *xprt;
  687.     struct svc_req *req;
  688. {
  689.     struct nfscreatargs *args;
  690.     struct nfsdiropres res;
  691.     char *fullpath, path[MAXPATHNAMELEN];
  692.  
  693.     args = (struct nfscreatargs *) malloc(sizeof(struct nfscreatargs));
  694.     if (args == NULL) {
  695.         (void) fprintf(stderr, mem_err);
  696.         abort();
  697.     }
  698.     (void) bzero((char*)args, sizeof(struct nfscreatargs));
  699.     if (! svc_getargs(xprt, xdr_diropargs, args)) {
  700.         svcerr_decode(xprt);
  701.         (void) free(args);
  702.         return;
  703.     }
  704.     if (NFS_READONLYFS) {
  705.         nfserr_readonlyfs(xprt, xdr_diropargs, args);
  706.         return;
  707.     }
  708.     /* construct path name of new directory */
  709.     fullpath = intopn(args->ca_da.da_fhandle.f.fh_fno, path);
  710.     if (fullpath != NULL) {
  711.         (void) strcat(fullpath, "\\");
  712.         (void) strcat(fullpath, args->ca_da.da_name);
  713.         (void) strtolower (fullpath);        /* force lower case */
  714.     }
  715.  
  716.     (void) bzero((char*)&res, sizeof(struct nfsdiropres));
  717.  
  718.     /* validate path name */
  719.     if ((res.dr_status = validate_path (fullpath)) == NFS_OK)
  720.         res.dr_status = mkdir(fullpath);
  721.  
  722.     if (res.dr_status == NFS_OK) {
  723.         res.dr_status = !file_getattr(fullpath, &(res.dr_attr));
  724.  
  725.         if (res.dr_status == NFS_OK)    /* make new file handle */
  726.           res.dr_fhandle = pntofh(fullpath);
  727.         else
  728.           res.dr_status = puterrno(errno);
  729.     }
  730.     if (! svc_sendreply(xprt, xdr_diropres, &res)) 
  731.         (void) fprintf(stderr, reply_err);
  732.     else if (NFS_VERBOSE)
  733.         (void) printf(">>> NFS_MKDIR: %s\n", fullpath);
  734.  
  735.     /* free all data */
  736.     svc_freeargs(xprt, xdr_creatargs, args);
  737. }
  738.  
  739. /*
  740.  *  void nfs_remove(SVCXPRT *xprt, struct svc_req *req) --
  741.  *      Remove a file specified by the handle.
  742.  */
  743. void nfs_remove(xprt, req)
  744.     SVCXPRT *xprt;
  745.     struct svc_req *req;
  746. {
  747.     struct nfsdiropargs *args;        /* dir op arguments */
  748.     enum nfsstat stat;            /* status of the remove */
  749.     char *fullpath, path[MAXPATHNAMELEN];    /* full path of file */
  750.  
  751.     args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
  752.     if (args == NULL) {
  753.         (void) fprintf(stderr, mem_err);
  754.         abort();
  755.     }
  756.     (void) bzero((char*)args, sizeof(struct nfsdiropargs));    /* zero it */
  757.     if (! svc_getargs(xprt, xdr_diropargs, args)) {
  758.         svcerr_decode(xprt);
  759.         (void) free(args);        /* couldn't decode it */
  760.         return;
  761.     }
  762.     if (NFS_READONLYFS) {
  763.         nfserr_readonlyfs(xprt, xdr_diropargs, &args);
  764.         return;
  765.     }
  766.     /* get full directory name from inode number */
  767.     fullpath = intopn(args->da_fhandle.f.fh_fno, path);
  768.     if (fullpath == NULL)
  769.         stat = NFSERR_NOENT;
  770.     else {
  771.         (void) strcat(fullpath, "\\");    /* append the name */
  772.         (void) strcat(fullpath, args->da_name);
  773.         stat = file_unlink(fullpath);
  774.     }
  775.     /* now reply to request */
  776.     if (! svc_sendreply(xprt, xdr_enum, &stat))
  777.         (void) fprintf(stderr, reply_err);
  778.     else if (NFS_VERBOSE)
  779.         (void) printf(">>> NFS_REMOVE: %s\n", fullpath);
  780.  
  781.     svc_freeargs(xprt, xdr_diropargs, args);
  782. }
  783.  
  784. /*
  785.  *  void nfs_rmdir(SVCXPRT *xprt, struct svc_req *req) --
  786.  *      Remove a directory specified by the handle.
  787.  */
  788. void nfs_rmdir(xprt, req)
  789.     SVCXPRT *xprt;
  790.     struct svc_req *req;
  791. {
  792.     struct nfsdiropargs *args;        /* dir op arguments */
  793.     enum nfsstat stat;            /* status of the remove */
  794.     char *fullpath, path[MAXPATHNAMELEN];    /* full path of file */
  795.     u_long node;
  796.  
  797.     args = (struct nfsdiropargs *) malloc(sizeof(struct nfsdiropargs));
  798.     if (args == NULL) {
  799.         (void) fprintf(stderr, mem_err);
  800.         abort();
  801.     }
  802.     (void) bzero((char*)args, sizeof(struct nfsdiropargs));    /* zero it */
  803.     if (! svc_getargs(xprt, xdr_diropargs, args)) {
  804.         svcerr_decode(xprt);
  805.         (void) free(args);        /* couldn't decode it */
  806.         return;
  807.     }
  808.     /* get full path name from inode number */
  809.     fullpath = intopn(args->da_fhandle.f.fh_fno, path);
  810.     if (fullpath == NULL)
  811.         stat = NFSERR_NOENT;            /* doesn't exist */
  812.     else {
  813.         (void) strcat(fullpath, "\\");        /* append the name */
  814.         (void) strcat(fullpath, args->da_name);
  815.         if (rmdir(fullpath)) {    /* remove it */
  816.             stat = (enum nfsstat) errno;
  817.  
  818.             /* Translate the error code so the correct message */
  819.             /* will be displayed. */
  820.             if (stat == NFSERR_ACCES)
  821.               stat = NFSERR_EXIST;
  822.         }
  823.         else {
  824.             stat = NFS_OK;
  825.             /* Remove the inode if assigned */
  826.             if ((node = pntoin (fullpath)) != -1)
  827.               inremnode (node);
  828.         }
  829.     }
  830.     /* now reply to request */
  831.     if (! svc_sendreply(xprt, xdr_enum, &stat))
  832.         (void) fprintf(stderr, reply_err);
  833.     else if (NFS_VERBOSE)
  834.         (void) printf(">>> NFS_RMDIR: %s\n", fullpath);
  835.  
  836.     svc_freeargs(xprt, xdr_diropargs, args);    /* free data */
  837. }
  838.  
  839. /*
  840.  *  void nfs_rename(SVCXPRT *xprt, struct svc_req *req) --
  841.  *      Renames given file to new name specified in the args.
  842.  */
  843. void nfs_rename(xprt, req)
  844.     SVCXPRT *xprt;
  845.     struct svc_req *req;
  846. {
  847.     struct nfsrnmargs *args;        /* arguments to rename */
  848.     enum nfsstat stat;            /* thr reply status */
  849.     char *oldname, *newname,        /* old and new filenames */
  850.       opath[MAXPATHNAMELEN], npath[MAXPATHNAMELEN];
  851.  
  852.     args = (struct nfsrnmargs *) malloc(sizeof(struct nfsrnmargs));
  853.     if (args == NULL) {
  854.         (void) fprintf(stderr, mem_err);
  855.         abort();
  856.     }
  857.     (void) bzero((char*)args, sizeof(struct nfsrnmargs));
  858.     if (! svc_getargs(xprt, xdr_rnmargs, args)) {
  859.         svcerr_decode(xprt);
  860.         (void) free(args);
  861.         return;
  862.     }
  863.     if (NFS_READONLYFS) {
  864.         nfserr_readonlyfs(xprt, xdr_rnmargs, args);
  865.         return;
  866.     }
  867.     /* make old name from inode */
  868.     oldname = intopn(args->rna_from.da_fhandle.f.fh_fno, opath);
  869.     newname = intopn(args->rna_to.da_fhandle.f.fh_fno, npath);
  870.     if (oldname == NULL || newname == NULL)    /* cannot find path for file */
  871.         stat = NFSERR_STALE;        /* ==> stale file handle */
  872.     else {
  873.         /* complete specification for names */
  874.         (void) strcat(oldname, "\\");
  875.         (void) strcat(oldname, args->rna_from.da_name);
  876.         (void) strcat(newname, "\\");
  877.         (void) strcat(newname, args->rna_to.da_name);
  878.  
  879.         /* Perform the rename operation */
  880.  
  881.         stat = file_rename(oldname, newname);
  882.     }
  883.     /* reply to rename request */
  884.     if (! svc_sendreply(xprt, xdr_enum, &stat))
  885.         (void) fprintf(stderr, reply_err);
  886.     else if (NFS_VERBOSE)
  887.         (void) fprintf(stderr, ">>> NFS_RENAME: %s to %s\n", 
  888.                 oldname, newname);
  889.     
  890.     /* free all data */
  891.     svc_freeargs(xprt, xdr_rnmargs, args);
  892. }
  893.  
  894. /*
  895.  *  void nfs_setattr(SVCXPRT *xprt, struct svc_req *req) --
  896.  *      Set file attributes.
  897.  */
  898. void nfs_setattr(xprt, req)
  899.     SVCXPRT *xprt;
  900.     struct svc_req *req;
  901. {
  902.     struct nfssaargs *args;            /* arguments */
  903.     struct nfsattrstat res;            /* results */
  904.  
  905.     args = (struct nfssaargs *) malloc(sizeof(struct nfssaargs));
  906.     if (args == NULL) {
  907.     (void) fprintf(stderr, mem_err);
  908.     abort();
  909.     }
  910.     (void) bzero((char*)args, sizeof(struct nfssaargs));
  911.     if (! svc_getargs(xprt, xdr_saargs, args)) {
  912.     svcerr_decode(xprt);
  913.     (void) free(args);
  914.     return;
  915.     }
  916.     DBGPRT4 (nfsdebug, "SETATTR: size = %ld  mode = %o%05o  time = %ld",
  917.          args->saa_sa.sa_size, (int) (args->saa_sa.sa_mode >> 15),
  918.          (int) args->saa_sa.sa_mode & 077777,
  919.          args->saa_sa.sa_mtime.tv_sec);
  920.     if (NFS_READONLYFS) {
  921.     nfserr_readonlyfs(xprt, xdr_saargs, args);
  922.     return;
  923.     }
  924.  
  925.     /* If a parameter in the argument block is not -1, set the  */
  926.     /* parameter within the file.                */
  927.  
  928.     /* File mode / protection */
  929.     res.ns_status = NFS_OK;
  930.     if (args->saa_sa.sa_mode != -1)
  931.       res.ns_status = file_setperm(args->saa_fh.f.fh_fno,
  932.                    args->saa_sa.sa_mode);
  933.  
  934.     /* Modification time */
  935.     if (res.ns_status == NFS_OK && args->saa_sa.sa_mtime.tv_sec > 0)
  936.       res.ns_status = file_settime(args->saa_fh.f.fh_fno,
  937.                    args->saa_sa.sa_mtime.tv_sec);
  938.  
  939.     /* Size */
  940.     if (res.ns_status == NFS_OK && args->saa_sa.sa_size != -1)
  941.       res.ns_status = file_setsize(args->saa_fh.f.fh_fno,
  942.                    args->saa_sa.sa_size);
  943.  
  944.     /* User ID / Group ID */
  945.     if (res.ns_status == NFS_OK && (args->saa_sa.sa_uid != -1 ||
  946.     args->saa_sa.sa_gid != -1))
  947.       res.ns_status = file_setowner(args->saa_fh.f.fh_fno,
  948.                     args->saa_sa.sa_uid, args->saa_sa.sa_gid);
  949.  
  950.     (void) bzero((char*)&res, sizeof(struct nfsattrstat));
  951.     if (res.ns_status == NFS_OK &&
  952.     !inattrget (args->saa_fh.f.fh_fno, &res.ns_attr)) {
  953.     res.ns_status = NFSERR_NOENT;
  954.     }
  955.  
  956.     if (! svc_sendreply(xprt, xdr_attrstat, &res))
  957.       (void) fprintf(stderr, reply_err);
  958.     else if (NFS_VERBOSE)
  959.       (void) printf(">>> NFS_SETATTR\n");
  960.     
  961.     /* free data */
  962.     svc_freeargs(xprt, xdr_saargs, args);
  963. }
  964.  
  965. /*
  966.  *  void nfs_link(SVCXPRT *xprt, struct svc_req *req) --
  967.  *      Create file link (not supported under DOS)
  968.  */
  969. void nfs_link(xprt, req)
  970.      SVCXPRT *xprt;
  971.      struct svc_req *req;
  972. {
  973.     struct nfslinkargs *args;        /* arguments to link */
  974.     struct nfsdiropres res;        /* return result */
  975.     enum nfsstat stat;            /* the reply status */
  976.     char *oldname, *newname,        /* old and new filenames */
  977.           opath[MAXPATHNAMELEN], npath[MAXPATHNAMELEN];
  978.  
  979.     args = (struct nfslinkargs *) malloc(sizeof(struct nfslinkargs));
  980.     if (args == NULL) {
  981.     (void) fprintf(stderr, mem_err);
  982.     abort();
  983.     }
  984.     (void) bzero((char*)args, sizeof(struct nfslinkargs));
  985.     (void) bzero((char*)&res, sizeof(struct nfsdiropres));
  986.     if (! svc_getargs(xprt, xdr_linkargs, args)) {
  987.     svcerr_decode(xprt);
  988.     (void) free(args);
  989.     return;
  990.     }
  991.     if (NFS_READONLYFS) {
  992.     nfserr_readonlyfs(xprt, xdr_linkargs, args);
  993.     return;
  994.     }
  995.     /* Translate inodes into names */
  996.     oldname = intopn(args->la_from.f.fh_fno, opath);
  997.     newname = intopn(args->la_to.da_fhandle.f.fh_fno, npath);
  998.     if (oldname == NULL || newname == NULL)    /* cannot find path for file */
  999.       stat = NFSERR_STALE;        /* ==> stale file handle */
  1000.     else {
  1001.     /* not supported:  return an error code */
  1002.  
  1003.     stat = NFSERR_ACCES;
  1004.     }
  1005.     res.dr_status = stat;
  1006.  
  1007.     if (! svc_sendreply(xprt, xdr_diropres, &res))
  1008.       (void) fprintf(stderr, reply_err);
  1009.     else if (NFS_VERBOSE)
  1010.       (void) fprintf(stderr, ">>> NFS_LINK: %s to %s\n", 
  1011.              oldname, newname);
  1012.     svc_freeargs(xprt, xdr_linkargs, args);
  1013. }
  1014.  
  1015.  
  1016. /*
  1017.  *  void nfs_symlink(SVCXPRT *xprt, struct svc_req *req) --
  1018.  *      Create symbolic link (not supported under DOS)
  1019.  */
  1020. void nfs_symlink(xprt, req)
  1021.      SVCXPRT *xprt;
  1022.      struct svc_req *req;
  1023. {
  1024.     struct nfsslargs  *args;        /* arguments to sym link */
  1025.     struct nfsrdlnres res;        /* return result */
  1026.     enum nfsstat stat;            /* the reply status */
  1027.     char *oldname, opath[MAXPATHNAMELEN]; /* old filename */
  1028.  
  1029.     args = (struct nfsslargs *) malloc(sizeof(struct nfsslargs));
  1030.     if (args == NULL) {
  1031.     (void) fprintf(stderr, mem_err);
  1032.     abort();
  1033.     }
  1034.     (void) bzero((char*)args, sizeof(struct nfsslargs));
  1035.     (void) bzero((char*)&res, sizeof(struct nfsrdlnres));
  1036.     if (! svc_getargs(xprt, xdr_slargs, args)) {
  1037.     svcerr_decode(xprt);
  1038.     (void) free(args);
  1039.     return;
  1040.     }
  1041.  
  1042.     /* Translate inode into name */
  1043.     oldname = intopn(args->sla_from.da_fhandle.f.fh_fno, opath);
  1044.     if (oldname == NULL)        /* cannot find path for file */
  1045.       stat = NFSERR_STALE;        /* ==> stale file handle */
  1046.     else {
  1047.     /* not supported:  return an error code */
  1048.  
  1049.     stat = NFSERR_ACCES;
  1050.     }
  1051.     res.rl_status = stat;
  1052.  
  1053.     if (! svc_sendreply(xprt, xdr_rdlnres, &res))
  1054.       (void) fprintf(stderr, reply_err);
  1055.     else if (NFS_VERBOSE)
  1056.       (void) fprintf(stderr, ">>> NFS_SYMLINK\n");
  1057.     svc_freeargs(xprt, xdr_linkargs, args);
  1058. }
  1059.  
  1060.  
  1061. /*
  1062.  *  void nfserr_readonlyfs(SVCXPRT *xprt, xdrproc_t xproc, void *args) --
  1063.  *      Return error status of NFSERR_ROFS.   Write attempted on read only
  1064.  *    file system.
  1065.  */
  1066. void nfserr_readonlyfs(xprt, xproc, args)
  1067.     SVCXPRT *xprt;
  1068.     xdrproc_t xproc;
  1069.     void *args;
  1070. {
  1071.     enum nfsstat err;
  1072.  
  1073.     err = NFSERR_ROFS;
  1074.     if (! svc_sendreply(xprt, xdr_enum, &err))
  1075.         (void) fprintf(stderr, reply_err);
  1076.     svc_freeargs(xprt, xproc, args);
  1077. }
  1078.